package martin.tpfinal.grabar.grafico;

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Line2D.Double;

import javax.swing.*;
import javax.swing.border.*;
import java.util.Vector;
import java.io.*;

import javax.sound.sampled.*;

public class VentanaPrincipal extends JPanel implements ActionListener {

	private static final long serialVersionUID = 1L;

	private final int bufSize = 16384;

	private FormatControls formatControls = new FormatControls();
	    
	private Reproducir playback = new Reproducir(this);

	private AudioInputStream audioInputStream;
	private SamplingGraph samplingGraph;

	private JButton playB, captB, pausB, loadB;
	private JButton saveWaveB;
	private JTextField textField;

	private String fileName = "untitled.wav";
	private String errStr;
	private double duration, seconds;
	private File file;
	private Vector<Double> lines = new Vector<Double>();

	private Capturar capture= new Capturar(this);

	
	
	public VentanaPrincipal() {
		
		inicialice();
	
	}

	private void inicialice(){
		
        setLayout(new BorderLayout());
        EmptyBorder eb = new EmptyBorder(5,5,5,5);
        SoftBevelBorder sbb = new SoftBevelBorder(SoftBevelBorder.LOWERED);
        setBorder(new EmptyBorder(5,5,5,5));

        JPanel p1 = new JPanel();
        p1.setLayout(new BoxLayout(p1, BoxLayout.X_AXIS));
        p1.add(formatControls);

        JPanel p2 = new JPanel();
        p2.setBorder(sbb);
        p2.setLayout(new BoxLayout(p2, BoxLayout.Y_AXIS));

        JPanel buttonsPanel = new JPanel();
        buttonsPanel.setBorder(new EmptyBorder(10,0,5,0));
        playB = addButton("Play", buttonsPanel, false);
        captB = addButton("Record", buttonsPanel, true);
        pausB = addButton("Pause", buttonsPanel, false);
        loadB = addButton("Load...", buttonsPanel, true);
        p2.add(buttonsPanel);

        JPanel samplingPanel = new JPanel(new BorderLayout());
        eb = new EmptyBorder(10,20,20,20);
        samplingPanel.setBorder(new CompoundBorder(eb, sbb));
        samplingPanel.add(samplingGraph = new SamplingGraph(this));
        p2.add(samplingPanel);

        JPanel savePanel = new JPanel();
        savePanel.setLayout(new BoxLayout(savePanel, BoxLayout.Y_AXIS));
     
        JPanel saveTFpanel = new JPanel();
        saveTFpanel.add(new JLabel("File to save:  "));
        saveTFpanel.add(textField = new JTextField(fileName));
        textField.setPreferredSize(new Dimension(140,25));
        savePanel.add(saveTFpanel);

        JPanel saveBpanel = new JPanel();
        saveWaveB = addButton("Save WAVE", saveBpanel, false);
        savePanel.add(saveBpanel);

        p2.add(savePanel);

        p1.add(p2);
        add(p1);

		
	}
	
    public void close() {
    	if (playback.getThread() != null) {
    		playB.doClick(0);
    	}
    	if (capture.getThread() != null) {
    		captB.doClick(0);
    	}
    }


    private JButton addButton(String name, JPanel p, boolean state) {
    	JButton b = new JButton(name);
    	b.addActionListener(this);
    	b.setEnabled(state);
    	p.add(b);
    	return b;
    }


    public void actionPerformed(ActionEvent e) {
    	Object obj = e.getSource();
    	if (obj.equals(saveWaveB)) {
    		saveToFile(textField.getText().trim(), AudioFileFormat.Type.WAVE);
    	} else if (obj.equals(playB)) {
    		if (playB.getText().startsWith("Play")) { //reproduccion
    			playback.start();
    			samplingGraph.start();
    			captB.setEnabled(false);
    			pausB.setEnabled(true);
    			playB.setText("Stop");
    		} else {  //para la reproduccion
    			playback.stop();
    			samplingGraph.stop();
    			captB.setEnabled(true);
    			pausB.setEnabled(false);
    			playB.setText("Play");
    		}
    	} else if (obj.equals(captB)) {
    		if (captB.getText().startsWith("Record")) { //empieza a grabar
    			file = null;
    			capture.start();
    			fileName = "untitled";
    			samplingGraph.start();
    			loadB.setEnabled(false);
    			playB.setEnabled(false);
    			pausB.setEnabled(true);
    			saveWaveB.setEnabled(false);
    			captB.setText("Stop");
    		} else {  //para de grabar
    			lines.removeAllElements();  
    			capture.stop();
    			samplingGraph.stop();
    			loadB.setEnabled(true);
    			playB.setEnabled(true);
    			pausB.setEnabled(false);
    			saveWaveB.setEnabled(true);
    			captB.setText("Record");
    		}
    	} else if (obj.equals(pausB)) {  //pausa lo que este haciendo
    		if (pausB.getText().startsWith("Pause")) {
    			if (capture.getThread() != null) {
    				capture.getLine().stop();
    			} else {
    				if (playback.getThread() != null) {
    					playback.getLine().stop();
    				}
    			}
    			pausB.setText("Resume");
    		} else {   //continua con lo que estaba haciendo
    			if (capture.getThread() != null) {
    				capture.getLine().start();
    			} else {
    				if (playback.getThread() != null) {
    					playback.getLine().start();
    				}
    			}
    			pausB.setText("Pause");
    		}
    	} else if (obj.equals(loadB)) { //carga un archivo desde una ubicacion
    				try {	
    					File file = new File(System.getProperty("user.dir"));
    					JFileChooser fc = new JFileChooser(file);
    					fc.setFileFilter(new javax.swing.filechooser.FileFilter () {
	    					public boolean accept(File f) {
		                        if (f.isDirectory()) {
		                            return true;
		                        }
		                        String name = f.getName();
		                        if ( name.endsWith(".wav") ) {
		                            return true;
		                        }
		                        return false;
		                    }
		                    public String getDescription() {
		                        return ".wav";
		                    }
		                });

		                if (fc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
		                    createAudioInputStream(fc.getSelectedFile(), true);
		                }
    				} catch (SecurityException ex) { 
    						showInfoDialog();
    						ex.printStackTrace();
    				} catch (Exception ex) { 
    						ex.printStackTrace();
    				}
	        	}
    }


    public static void showInfoDialog() {
    	final String msg = 
    		"When running the Java Sound demo as an applet these permissions\n" +
    		"are necessary in order to load/save files and record audio :  \n\n"+
    		"grant { \n" +
    		"  permission java.io.FilePermission \"<<ALL FILES>>\", \"read, write\";\n" +
    		"  permission javax.sound.sampled.AudioPermission \"record\"; \n" +
    		"  permission java.util.PropertyPermission \"user.dir\", \"read\";\n"+
    		"}; \n\n" +
    		"The permissions need to be added to the .java.policy file.";
    	new Thread(new Runnable() {
    		public void run() {
    			JOptionPane.showMessageDialog(null, msg, "Applet Info", JOptionPane.INFORMATION_MESSAGE);
    		}
    	}).start();
    }


    public void createAudioInputStream(File file, boolean updateComponents) {
    	if (file != null && file.isFile()) {
    		try {
    			this.file = file;
    			errStr = null;
    			audioInputStream = AudioSystem.getAudioInputStream(file);
    			playB.setEnabled(true);
    			fileName = file.getName();
    			long milliseconds = (long)((audioInputStream.getFrameLength() * 1000) / audioInputStream.getFormat().getFrameRate());
    			duration = milliseconds / 1000.0;
    			saveWaveB.setEnabled(true);
    			if (updateComponents) {
    				formatControls.setFormat(audioInputStream.getFormat());
    				samplingGraph.createWaveForm(null);
    			}
    		} catch (Exception ex) { 
    			reportStatus(ex.toString());
    		}
    	} else {
    		reportStatus("Audio file required.");
    	}	
    }


    public void saveToFile(String name, AudioFileFormat.Type fileType) {

    	if (audioInputStream == null) {
    		reportStatus("No loaded audio to save");
    		return;
    	} else if (file != null) {
    		createAudioInputStream(file, false);
    	}

    	// reset to the beginnning of the captured data
    	try {
    		audioInputStream.reset();
    	} catch (Exception e) { 
    		reportStatus("Unable to reset stream " + e);
    		return;
    	}

    	File file = new File(fileName = name);
    	try {
    		if (AudioSystem.write(audioInputStream, fileType, file) == -1) {
    			throw new IOException("Problems writing to file");
    		}
    		else {
				System.out.println("hola");
			}
    	} catch (Exception ex) { reportStatus(ex.toString()); }
    		samplingGraph.repaint();
    }
	        

    public void reportStatus(String msg) {
    	if ((errStr = msg) != null) {
    		System.out.println(errStr);
    		samplingGraph.repaint();
    	}
    }


    public String getErrStr() {
		return errStr;
	}

	public void setErrStr(String errStr) {
		this.errStr = errStr;
	}

	public SamplingGraph getSamplingGraph() {
		return samplingGraph;
	}

	public void setSamplingGraph(SamplingGraph samplingGraph) {
		this.samplingGraph = samplingGraph;
	}

	public JButton getCaptB() {
		return captB;
	}

	public void setCaptB(JButton captB) {
		this.captB = captB;
	}

	public JButton getPlayB() {
		return playB;
	}

	public void setPlayB(JButton playB) {
		this.playB = playB;
	}

	public JButton getPausB() {
		return pausB;
	}

	public void setPausB(JButton pausB) {
		this.pausB = pausB;
	}

	public File getFile() {
		return file;
	}

	public void setFile(File file) {
		this.file = file;
	}

	public AudioInputStream getAudioInputStream() {
		return audioInputStream;
	}

	public void setAudioInputStream(AudioInputStream audioInputStream) {
		this.audioInputStream = audioInputStream;
	}

	public FormatControls getFormatControls() {
		return formatControls;
	}

	public void setFormatControls(FormatControls formatControls) {
		this.formatControls = formatControls;
	}

	public int getBufSize() {
		return bufSize;
	}

    public Vector<Double> getLines() {
		return lines;
	}

	public void setLines(Vector<Double> lines) {
		this.lines = lines;
	}

	public double getDuration() {
		return duration;
	}

	public void setDuration(double duration) {
		this.duration = duration;
	}

	public double getSeconds() {
		return seconds;
	}

	public void setSeconds(double seconds) {
		this.seconds = seconds;
	}

	public Capturar getCapture() {
		return capture;
	}

	public void setCapture(Capturar capture) {
		this.capture = capture;
	}

	public String getFileName() {
		return fileName;
	}

	public void setFileName(String fileName) {
		this.fileName = fileName;
	}

	public Reproducir getPlayback() {
		return playback;
	}

	public void setPlayback(Reproducir playback) {
		this.playback = playback;
	}

    public JButton getLoadB() {
		return loadB;
	}

	public void setLoadB(JButton loadB) {
		this.loadB = loadB;
	}

	public JButton getSaveWaveB() {
		return saveWaveB;
	}

	public void setSaveWaveB(JButton saveWaveB) {
		this.saveWaveB = saveWaveB;
	}

	    
}
